import {
  Controller,
  Get,
  Post,
  Body,
  Put,
  Delete,
  Param,
  Query,
  Logger,
  HttpException,
  HttpStatus,
  ParseIntPipe,
  ValidationPipe,
  UseGuards,
} from "@nestjs/common";
import { MenusService } from "./menus.service";
import { CreateMenuDto, UpdateMenuDto, QueryMenuDto } from "./dto";
import { ConfigService } from "@nestjs/config";
import { JwtGuard } from "../guards/jwt.guard";
import { Can, CheckPolicies } from "../decorators/casl.decorator";
import { Action } from "src/enum/action.enum";
import { CaslGuard } from "src/guards/casl.guard";
import { Menus } from "./menu.entity";
import { AdminGuard } from "../guards/admin.guard";

/**
 * 菜单控制器 - 处理菜单相关的HTTP请求
 */
@Controller("menus")
// @CheckPolicies((ability) => ability.can(Action.READ, Menus))
// @Can(Action.READ, Menus)
@UseGuards(JwtGuard, AdminGuard, CaslGuard)
export class MenusController {
  private logger = new Logger(MenusController.name);

  // 依赖注入：菜单服务和配置服务
  constructor(
    private readonly menusService: MenusService,
    private readonly configService: ConfigService,
  ) {
    this.logger.log("MenusController initialized");
  }

  /**
   * 获取所有菜单（不分页）
   */
  @Get("list")
  @Can(Action.UPDATE, Menus)
  // @Can(Action.UPDATE, Logs)
  async findAll() {
    try {
      const menus = await this.menusService.findAll();
      this.logger.log(`查询所有菜单成功，共 ${menus.length} 个菜单`);
      return menus;
    } catch (error) {
      this.logger.error(`查询所有菜单失败: ${error.message}`, error.stack);
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "查询菜单列表失败",
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 根据访问控制权限查询菜单
   * @param acl 访问控制权限
   */
  @Get("acl/:acl")
  async findByAcl(@Param("acl") acl: string) {
    try {
      const menus = await this.menusService.findByAcl(acl);
      this.logger.log(`根据ACL查询菜单成功: ${acl}，共 ${menus.length} 个菜单`);
      return menus;
    } catch (error) {
      this.logger.error(`根据ACL查询菜单失败: ${error.message}`, error.stack);
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "根据访问控制权限查询菜单失败",
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 根据路径查找菜单
   * @param path 菜单路径（需要URL编码）
   */
  @Get("path/:path")
  async findByPath(@Param("path") path: string) {
    try {
      // 解码URL编码的路径
      const decodedPath = decodeURIComponent(path);
      const menu = await this.menusService.findByPath(decodedPath);
      this.logger.log(`根据路径查询菜单: ${decodedPath}，${menu ? "找到菜单" : "未找到菜单"}`);
      return menu;
    } catch (error) {
      this.logger.error(`根据路径查询菜单失败: ${error.message}`, error.stack);
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "根据路径查询菜单失败",
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 分页获取菜单列表（支持多条件搜索）
   */
  @Get("page")
  @Can(Action.READ, Menus)
  async getPaginatedMenus(@Query(ValidationPipe) queryDto: QueryMenuDto) {
    try {
      const result = await this.menusService.getPaginatedMenus(queryDto);
      this.logger.log(`分页查询菜单成功，页码: ${queryDto.page || 1}，共 ${result.data.total} 个菜单`);
      return result;
    } catch (error) {
      this.logger.error(`分页查询菜单失败: ${error.message}`, error.stack);
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "查询菜单列表失败",
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 创建新菜单
   * @param createMenuDto 菜单创建信息
   */
  @Post()
  async create(@Body(ValidationPipe) createMenuDto: CreateMenuDto) {
    try {
      const newMenu = await this.menusService.create(createMenuDto);
      this.logger.log(`创建菜单成功: ${newMenu.name} (ID: ${newMenu.id})`);
      return newMenu;
    } catch (error) {
      this.logger.error(`创建菜单失败: ${error.message}`, error.stack);
      const status = error.message.includes("已存在") ? HttpStatus.CONFLICT : HttpStatus.INTERNAL_SERVER_ERROR;
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "创建菜单失败",
        },
        status,
      );
    }
  }

  /**
   * 根据ID查找菜单
   * @param id 菜单ID
   */
  @Get(":id")
  async findOne(@Param("id", ParseIntPipe) id: number) {
    try {
      const menu = await this.menusService.findOne(id);
      this.logger.log(`根据ID查找菜单成功: ${id}`);
      return menu;
    } catch (error) {
      this.logger.error(`根据ID查找菜单失败: ${error.message}`, error.stack);
      const status = error.message.includes("不存在") ? HttpStatus.NOT_FOUND : HttpStatus.INTERNAL_SERVER_ERROR;
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "查询菜单详情失败",
        },
        status,
      );
    }
  }
  /**
   * 更新菜单信息
   * @param id 菜单ID
   * @param updateMenuDto 更新的菜单信息
   */
  @Put(":id")
  async update(@Param("id", ParseIntPipe) id: number, @Body(ValidationPipe) updateMenuDto: UpdateMenuDto) {
    try {
      const result = await this.menusService.update(id, updateMenuDto);
      this.logger.log(`更新菜单成功: ID ${id}`);
      return result;
    } catch (error) {
      this.logger.error(`更新菜单失败: ${error.message}`, error.stack);
      let status = HttpStatus.INTERNAL_SERVER_ERROR;
      if (error.message.includes("不存在")) {
        status = HttpStatus.NOT_FOUND;
      } else if (error.message.includes("已存在")) {
        status = HttpStatus.CONFLICT;
      }
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "更新菜单失败",
        },
        status,
      );
    }
  }

  /**
   * 删除菜单
   * @param id 菜单ID
   */
  @Delete(":id")
  async remove(@Param("id", ParseIntPipe) id: number) {
    try {
      const result = await this.menusService.remove(id);
      this.logger.log(`删除菜单成功: ID ${id}`);
      return result;
    } catch (error) {
      this.logger.error(`删除菜单失败: ${error.message}`, error.stack);
      let status = HttpStatus.INTERNAL_SERVER_ERROR;
      if (error.message.includes("不存在")) {
        status = HttpStatus.NOT_FOUND;
      } else if (error.message.includes("关联数据")) {
        status = HttpStatus.CONFLICT;
      }
      throw new HttpException(
        {
          success: false,
          message: error.message,
          error: "删除菜单失败",
        },
        status,
      );
    }
  }
}
